# @File    : probe_calib_X.py
"""
用于标定探头
"""
import os
import PyQt5.Qt
import common
import ezqt
from autogen.probe_calibration import Ui_Form
class GroupVBMeasurerTask(common.AbstractMeasurerTask):
    sig_recorder_update = PyQt5.Qt.pyqtSignal(common.RecorderForVtoB_One_Probe)
    def __init__(self, hm: common.HallMachine, recorder: common.RecorderForVtoB_One_Probe, B_ground_truth: float,
                 records: int = 10,
                 timer: PyQt5.Qt.QTimer = common.DataExchangerTimer):
        super(GroupVBMeasurerTask, self).__init__()
        self.hm = hm
        self.recorder = recorder
        self.timer = timer
        self.B_ground_truth = B_ground_truth
        self.remain_records = records
        self.done = False
        self.start_from = self.recorder.df.shape[0]
    def __on_timer(self):
        """
        :return:
        """
        if self.remain_records <= 0 or self.done:
            return self.stop()
        self.hm.update_GPIB()
        self.recorder.push_back(self.hm, self.B_ground_truth)
        self.remain_records -= 1
    def stop(self):
        self.done = True
        self.timer.timeout.disconnect(self.__on_timer)
        self.sig_recorder_update.emit(self.recorder)
    def start(self):
        self.timer.timeout.connect(self.__on_timer)
class ProbeCalibX(Ui_Form, PyQt5.Qt.QObject):
    PROBE_DICT = {
        "X方向": common.Axis.X,
        "Y方向": common.Axis.Y,
        "Z方向": common.Axis.Z,
    }
    sig_task_OK = PyQt5.Qt.pyqtSignal()
    def __init__(self, hm: common.HallMachine, parent: PyQt5.Qt.QWidget, timer=common.DEFAULT_MAIN_TIMER):
        super(ProbeCalibX, self).__init__()
        self.hm = hm
        self.hm_helper = common.HallMachineAxisHelper(hm)
        self.__parent = parent
        self.__timer = timer
        self.task_BV_measurer = None
        self.setupUi()
    def setupUi(self):
        super(ProbeCalibX, self).setupUi(self.__parent)
        self.lineEdit_records.setValidator(PyQt5.Qt.QDoubleValidator())
        self.__init_comboBox()
        self.__init_linedit_B_and_add_group()
        self.__show_last_update_time()
        self.__timer.timeout.connect(self.__show_V)
        self.pushButton_add_a_group.clicked.connect(self.__on_add_one_group_B_V)
        self.pushButton_del_this.clicked.connect(self.__on_delete_selected_rows)
        self.pushButton_edit_in_excel.clicked.connect(self.__on_push_open_in_excel)
        self.pushButton_refresh.clicked.connect(self.__on_refresh)
        self.pushButton_OK_to_write.clicked.connect(self.__on_push_OK_to_write)
        self.pushButton_clear_all.clicked.connect(self.__on_push_clear_all)
    def __on_push_clear_all(self):
        self.__recorder_for_one_probe.df.drop(index=self.__recorder_for_one_probe.df.index, inplace=True)
        ezqt.df_to_QTableWidget_with_header(self.__recorder_for_one_probe.get_brief(), self.tableWidget_res)
    def __init_comboBox(self):
        self.comboBox_choose_probe.addItems(self.PROBE_DICT.keys())
        self.__recorder_for_one_probe = common.RecorderForVtoB_One_Probe(self.__get_prob_to_be_calibrated())
        self.__on_refresh()
        self.comboBox_choose_probe.currentTextChanged.connect(self.__on_comboBox_text_changed)
    def __on_comboBox_text_changed(self, new_text: str):
        self.__recorder_for_one_probe = common.RecorderForVtoB_One_Probe(self.PROBE_DICT[new_text])
        self.__on_refresh()
        self.__show_last_update_time()
    def __init_linedit_B_and_add_group(self):
        self.lineEdit_B.setValidator(PyQt5.Qt.QDoubleValidator())
        self.lineEdit_B.textChanged.connect(self.__on_lineEdit_B_text_changed)
    def __on_lineEdit_B_text_changed(self, new_text: str):
        self.pushButton_add_a_group.setDisabled(not new_text)
    def __disable_when_measure(self, stats: bool):
        self.lineEdit_B.setDisabled(stats)
        self.comboBox_choose_probe.setDisabled(stats)
        self.pushButton_clear_all.setDisabled(stats)
        self.lineEdit_records.setDisabled(stats)
        self.pushButton_add_a_group.setDisabled(stats)
    def __on_add_one_group_B_V(self):
        self.task_BV_measurer = \
            GroupVBMeasurerTask(
                self.hm, self.__recorder_for_one_probe, float(self.lineEdit_B.text()),
                int(self.lineEdit_records.text()), self.__timer
            )
        self.__disable_when_measure(True)
        self.__update_record()
        self.task_BV_measurer.start()
        self.task_BV_measurer.sig_recorder_update.connect(self.__on_recorder_update)
    def __on_recorder_update(self, new_recorder: common.RecorderForVtoB_One_Probe):
        self.__disable_when_measure(False)
        ezqt.df_to_QTableWidget_with_header(self.__recorder_for_one_probe.get_brief(), self.tableWidget_res)
    def __show_V(self):
        self.lineEdit_V_relative.setText(
            "%.4f" % (self.hm_helper.d_get_V_relative[self.__recorder_for_one_probe.get_axis()]()))
    def __get_prob_to_be_calibrated(self) -> common.Axis:
        return self.PROBE_DICT[self.comboBox_choose_probe.currentText()]
    def __show_last_update_time(self):
        time_str = self.__recorder_for_one_probe.get_update_time_str()
        self.label_last_time_calib.setText(time_str)
    def __on_push_OK_to_write(self):
        if self.__recorder_for_one_probe.ready_to_write():
            return self.__recorder_for_one_probe.to_csv()
        new_window = PyQt5.Qt.QMainWindow()
        PyQt5.Qt.QMessageBox.critical(
            new_window, "写入失败",
            "标定点数过少，写入失败！需要记录至少%d个不同的B值。" % self.__recorder_for_one_probe.MIN_VALUE_COUNT_OF_B)
        new_window.show()
    def __on_delete_selected_rows(self):
        ezqt.drop_selected_rows(self.tableWidget_res)
    def __update_record(self):
        """
        修改了tableWidget时，让recorder与之同步
        :return:
        """
        self.__recorder_for_one_probe.df.drop(index=self.__recorder_for_one_probe.df.index, inplace=True)
        self.__recorder_for_one_probe.df[self.__recorder_for_one_probe.used_columns] = ezqt.QTableWidget_to_df(
            self.tableWidget_res, False)
        print(self.__recorder_for_one_probe.df)
    def __on_push_open_in_excel(self):
        self.__update_record()
        temp_csv_path = self.__temp_csv_path()
        self.__recorder_for_one_probe.df.to_csv(temp_csv_path, index=False)
        os.system("start %s" % temp_csv_path)
    def __temp_csv_path(self):
        return os.path.join(common.TEMP_DIR,
                            os.path.split(self.__recorder_for_one_probe.autogen_path_method())[1])
    def __on_refresh(self, ):
        """
        自动选择temp文件夹和config文件夹中最新者，展示在tableWidget中。
        若均不存在，则在内存中新建一个。
        :return:
        """
        cfg_csv_mod_time = temp_csv_mod_time = 0
        temp_csv_path = self.__temp_csv_path()
        if os.path.exists(temp_csv_path):
            temp_csv_mod_time = os.path.getmtime(temp_csv_path)
        cfg_csv_path = self.__recorder_for_one_probe.autogen_path_method()
        if os.path.exists(cfg_csv_path):
            cfg_csv_mod_time = os.path.getmtime(cfg_csv_path)
        if temp_csv_mod_time > cfg_csv_mod_time:
            self.__recorder_for_one_probe.read_csv(temp_csv_path)
            print("Use temp: %s" % temp_csv_path)
        else:
            self.__recorder_for_one_probe.read_csv()
            print("Use config or create new")
        ezqt.df_to_QTableWidget_with_header(self.__recorder_for_one_probe.get_brief(), self.tableWidget_res)
if __name__ == '__main__':
    from PyQt5.Qt import QApplication
    import sys
    app = QApplication([])
    main_timer = common.DEFAULT_MAIN_TIMER
    hm = common.HallMachine()
    main_timer.timeout.connect(hm.update_all)
    main_window = PyQt5.Qt.QMainWindow()
    main_widget = PyQt5.Qt.QWidget(main_window)
    main_window.setCentralWidget(main_widget)
    probe_calib_x = ProbeCalibX(hm, main_widget, main_timer)
    main_timer.start()
    main_window.show()
    sys.exit(app.exec_())
